package com.hzj.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    //    1.创建realm对象(这里是自定义了一个类)
    @Bean("studentRealm")
    public StudentRealm studentRealm() {
        return new StudentRealm();
    }

    //   2.创建DefaultWebSecurityManager对象
    @Bean("securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("studentRealm") StudentRealm studentRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        关联studentRealm，存入StudentRealm对象，StudentRealm为形参参数,
        securityManager.setRealm(studentRealm);
        //配置记住我 参考博客：
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    //   3.创建
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//        设置安全管理器
        bean.setSecurityManager(securityManager);
//         添加shiro内置过滤器
        /**
         *anon:无需认证就可以访问
         * authc:必须认证了才能让问
         * user:必须拥有记住我功能才能用
         * perms :拥有对某个资源的权限才能访问;
         * role:拥有某个角色权限才能访问
         */
//        设置拦截与授权
        Map<String, String> fiterMap = new LinkedHashMap<>();
//        授权
        fiterMap.put("/toadmin", "perms[user:add]");//perms[user:add]设置权限，并且会进入StudentRealm类的授权方法，并且在授权方法中授权了[]内的指定内容该用户才能访问指定的页面
//        拦截
        fiterMap.put("/add", "authc");//对对应的地址设置相应的权限，authc:必须认证了才能让问,并且会进入StudentRealm类的认证方法
        fiterMap.put("/update", "authc");
        bean.setFilterChainDefinitionMap(fiterMap);//存入
//        设置登录的请求,没有权限就会跳转到指定页面
        bean.setLoginUrl("/tologin");
//        设置未授权请求，没有权限就会跳转到指定页面
        bean.setUnauthorizedUrl("/unauthorized");
        return bean;
    }

    //整合shiroDialect：用来整合shiro thymeleaf
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
    /**
     * cookie对象;会话Cookie模板 ,默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid或rememberMe，自定义
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //setcookie的httponly属性如果设为true的话，会增加对xss防护的安全系数。它有以下特点：

        //setcookie()的第七个参数
        //设为true后，只能通过http访问，javascript无法访问
        //防止xss读取cookie
        simpleCookie.setHttpOnly(true);
        simpleCookie.setPath("/");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(2592000);
        return simpleCookie;
    }
    /**
     * cookie管理对象;记住我功能,rememberMe管理器
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }
    /**
     * FormAuthenticationFilter 过滤器 过滤记住我
     * @return
     */
//    @Bean
//    public FormAuthenticationFilter formAuthenticationFilter(){
//        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
//        //对应前端的checkbox的name = rememberMe
//        formAuthenticationFilter.setRememberMeParam("rememberMe");
//        return formAuthenticationFilter;
//    }
}
